﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UCL.Powersource.Mock;

namespace Powersource_UnitTests.StatisticsTest
{
    [TestClass]
    public class StatisticCompareTeamsBaseTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        #endregion

        private DummyStatistic2 stat;
        private DummyTeamProjectCollectionConfiguration teamProjCollConfig;
        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize()
        {
            stat = new DummyStatistic2();
            teamProjCollConfig = new DummyTeamProjectCollectionConfiguration();
        }

        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            stat = null;
            teamProjCollConfig = null;
        }

        [TestMethod]
        public void CompareTeamStatTestResolveTwoProjectsOneTimeframe()
        {
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var proj2 = teamProjCollConfig.TeamProjectConfigurations[1];
            var proj5 = teamProjCollConfig.TeamProjectConfigurations[4];
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            var timeframe2 = teamProjCollConfig._ProjectCollectionTimeFrames[1];
            stat.Resolve(proj1, proj2, timeframe);
            Assert.IsTrue(stat.CompareTeamResults.ContainsKey(proj1), "No entry for {0} in TeamResults", proj1.UniqueName);
            Assert.IsTrue(stat.CompareTeamResults[proj1].ContainsKey(timeframe), "No entry for {0}:{1} in TeamResults", proj1.UniqueName, timeframe.Label);
            Assert.IsFalse(stat.CompareTeamResults[proj1].ContainsKey(timeframe2), "Entry created for {0}:{1} when not requested", proj1.UniqueName, timeframe2.Label);
            var result = stat.CompareTeamResults[proj1][timeframe].FirstOrDefault(a => a.TeamProject == proj2 && a.StatTimeFrame == timeframe);
            Assert.IsNotNull(result, "Null value for {0}:{1}:{2} in TeamResults", proj1.UniqueName, timeframe.Label, proj2.UniqueName);

            result = stat.CompareTeamResults[proj1][timeframe].FirstOrDefault(a => a.TeamProject == proj1);
            Assert.IsNull(result, "Project {0}:{1} contains entry for itself", proj1.UniqueName, timeframe.Label);

            Assert.IsTrue(stat.CompareTeamResults.ContainsKey(proj2), "No entry for {0} in TeamResults", proj1.UniqueName);
            Assert.IsTrue(stat.CompareTeamResults[proj2].ContainsKey(timeframe), "No entry for {0}:{1} in TeamResults", proj1.UniqueName, timeframe.Label);
            Assert.IsFalse(stat.CompareTeamResults[proj2].ContainsKey(timeframe2), "Entry created for {0}:{1} when not requested", proj1.UniqueName, timeframe2.Label);
            result = stat.CompareTeamResults[proj2][timeframe].FirstOrDefault(a => a.TeamProject == proj1 && a.StatTimeFrame == timeframe);
            Assert.IsNotNull(result, "Null value for {0}:{1}:{2} in TeamResults", proj2.UniqueName, timeframe.Label, proj1.UniqueName);

            stat.Resolve(proj1, proj5, timeframe);
            Assert.IsFalse(stat.TeamResults.ContainsKey(proj5), "Entry created for {0} even though it was not set for statistics", proj5.UniqueName);
            result = stat.CompareTeamResults[proj1][timeframe].FirstOrDefault(a => a.TeamProject == proj5);
            Assert.IsNull(result, "Entry created for {0}:{1}:{2} even though it was not set for statistics",proj1.UniqueName, timeframe.Label, proj5.UniqueName);
        }

        [TestMethod]
        public void CompareTeamStatTestResolveTwoProjectsOneTimeframeForceRecalculate()
        {
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var proj2 = teamProjCollConfig.TeamProjectConfigurations[1];
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            stat.Resolve(proj1, proj2, timeframe);
            var result = stat.CompareTeamResults[proj1][timeframe].FirstOrDefault(a => a.TeamProject == proj2 && a.StatTimeFrame == timeframe);
            stat.Resolve(proj1, proj2, timeframe, true);
            var result2 = stat.CompareTeamResults[proj1][timeframe].FirstOrDefault(a => a.TeamProject == proj2 && a.StatTimeFrame == timeframe);

            Assert.AreNotEqual(result, result2, "Result not properly recalculated");
        }

        [TestMethod]
        public void CompareTeamStatTestResolveOneProjectCollectionAllTimeframes()
        {
            stat.Resolve(teamProjCollConfig);

            foreach (var proj in teamProjCollConfig)
            {
                if (proj != teamProjCollConfig.TeamProjectConfigurations[4])
                {
                    Assert.IsTrue(stat.CompareTeamResults.ContainsKey(proj), "No entry for {0} in CompareTeamResults", proj.UniqueName);
                    foreach (var timeframe in teamProjCollConfig.ProjectCollectionTimeFrames)
                    {
                        Assert.IsTrue(stat.CompareTeamResults[proj].ContainsKey(timeframe), "No entry for {0}:{1} in CompareTeamResults", proj.UniqueName, timeframe.Label);
                        Assert.AreEqual(3, stat.CompareTeamResults[proj][timeframe].Count, "Number of results for {0}:{1} different than expected", proj.UniqueName, timeframe.Label);
                    }

                }
            }
        }

        [TestMethod]
        public void CompareTeamStatTestClearInvalidEntries()
        {
            stat.Resolve(teamProjCollConfig);
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            teamProjCollConfig.TeamProjectConfigurations.Remove(proj1);
            teamProjCollConfig._ProjectCollectionTimeFrames.Remove(timeframe);

            stat.ClearInvalidEntries(teamProjCollConfig);

            Assert.IsFalse(stat.CompareTeamResults.ContainsKey(proj1), "Results still contain entry for {0}", proj1.UniqueName);
            foreach (var entry in stat.CompareTeamResults)
            {
                Assert.IsFalse(entry.Value.ContainsKey(timeframe), "Results still contain entry for {0}:{1}", entry.Key.UniqueName, timeframe.Label);
            }

            foreach (var dict in stat.CompareTeamResults.Values)
            {
                foreach (var coll in dict.Values)
                {
                    var res = coll.FirstOrDefault(a => a.TeamProject == proj1 || a.StatTimeFrame == timeframe);
                    Assert.IsNull(res, "Inside entry for removed item found");
                }
            }
        }
    }
}
